/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ola_tls_adapter.h"
#include <stddef.h>
#include <netdb.h>
#include "mbedtls/debug.h"
#include "mbedtls/entropy_poll.h"
#include "mbedtls/base64.h"
#include "mbedtls/platform_time.h"
#include "mbedtls/x509.h"
#include "ola_log.h"
#include "ola_error.h"
#include "ola_base_utils.h"
#include "ola_time.h"
#include "ola_pal_os.h"
#include "ola_random.h"

#define TLS_TCP_READ_TIMEOUT 50
#define TLS_TCP_SEND_TIMEOUT 50

#define TLS_HANDSHAKE_TIMEOUT    4000
#define DEBUG_LEVEL                 4
#define CERT_NUMBER                 2

/* 支持证书的最大层数 */
#define MAX_CERT_DEPTH              4
#define MS_PER_SECOND 1000

/* 支持的最大加密套件数 */
#ifndef MAX_CIPHERSUITES_NUM
#define MAX_CIPHERSUITES_NUM        20
#endif

typedef struct {
    mbedtls_x509_time start;
    mbedtls_x509_time end;
} CertValidDate;

/* mbedtls套件白名单, 具体套件ID定义见mbedtls中的ssl_cipersuites.h */
#define MBEDTLS_SSL_CIPERSUITE_WHITE_LIST   MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,    \
    MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,   \
    MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256

/* 支持的mbedtls套件白名单 */
static const int SUPPORT_CIPHERSUITE[] = {MBEDTLS_SSL_CIPERSUITE_WHITE_LIST};

#define MAX_SUPPORT_CIPHERSUITE_NUM (sizeof(SUPPORT_CIPHERSUITE) / sizeof(int))

/* 代码内置的根证书 */
static const unsigned char g_caPem1[] =
    "-----BEGIN CERTIFICATE-----\r\n"
    "MIIF1DCCBVqgAwIBAgIEEAAADzAKBggqhkjOPQQDAzA1MQswCQYDVQQGEwJDTjEM\r\n"
    "MAoGA1UECgwDT0xBMRgwFgYDVQQDDA9PTEEgRUNDIFJPT1QgQ0EwHhcNMjEwNDA5\r\n"
    "MDk0MTU3WhcNNDEwNDA0MDk0MTU3WjBdMQswCQYDVQQGEwJDTjEPMA0GA1UECgwG\r\n"
    "SHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMSgwJgYDVQQDDB9IdWF3ZWkgQ0JH\r\n"
    "IEVxdWlwbWVudCBTMSBDQSBUZXN0MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEPOfL\r\n"
    "ryxsu3lSdX4ShqmIN55ZCTfYlaITucFG7M/zJJgCbjoYsexMxCkhk/qZxQzT2PCs\r\n"
    "AYSo4d2nELCrpFpc2kaM74Nroj4CiZnNAZ/y28NnrvqSaFvlSye6gkgdozeTo4IE\r\n"
    "ETCCBA0wHQYDVR0OBBYEFOWTzykFL2dTqqhniJBsfOlGEBMMMIIBDgYDVR0fBIIB\r\n"
    "BTCCAQEwbKBqoGiGZmxkYXA6Ly9wa2kub2xhLWlvdC5jb206MzkxL2NuPWFybDAs\r\n"
    "c3Q9MixvPU9MQSBFQ0MgUk9PVCBDQUFSTCxPPU9MQSxDPUNOP2F1dGhvcml0eVJl\r\n"
    "dm9jYXRpb25MaXN0O2JpbmFyeTBboFmgV6RVMFMxCzAJBgNVBAYTAkNOMQwwCgYD\r\n"
    "VQQKDANPTEExGzAZBgNVBAoMEk9MQSBFQ0MgUk9PVCBDQUFSTDEKMAgGA1UECAwB\r\n"
    "MjENMAsGA1UEAwwEYXJsMDA0oDKgMIYuaHR0cDovL3BraS5vbGEtaW90LmNvbTox\r\n"
    "MDAwNC9lY2NmaWxlLzJhcmwwLmNybDBgBgNVHSMEWTBXgBTHlelr1uJVGfbt/HAD\r\n"
    "YLxTpVe14KE5pDcwNTELMAkGA1UEBhMCQ04xDDAKBgNVBAoMA09MQTEYMBYGA1UE\r\n"
    "AwwPT0xBIEVDQyBST09UIENBggQQAAANMBIGA1UdEwEB/wQIMAYBAf8CAQIwDgYD\r\n"
    "VR0PAQH/BAQDAgEGMIH7BggrBgEFBQcBAQSB7jCB6zBZBggrBgEFBQcwAoZNbGRh\r\n"
    "cDovL3BraS5vbGEtaW90LmNvbTozOTEvQ049T0xBIEVDQyBST09UIENBLE89T0xB\r\n"
    "LEM9Q04/Y0FDZXJ0aWZpY2F0ZTtiaW5hcnkwQwYIKwYBBQUHMAKkNzA1MQswCQYD\r\n"
    "VQQGEwJDTjEMMAoGA1UECgwDT0xBMRgwFgYDVQQDDA9PTEEgRUNDIFJPT1QgQ0Ew\r\n"
    "SQYIKwYBBQUHMAKGPWh0dHA6Ly9wa2kub2xhLWlvdC5jb206MTAwMDQvZWNjZmls\r\n"
    "ZS9PTEFFQ0NST09UQ0ExMDAwMDAwZC5jZXIwggFUBggrBgEFBQcBCwSCAUYwggFC\r\n"
    "MHoGCCsGAQUFBzAFhm5sZGFwOi8vcGtpLm9sYS1pb3QuY29tOjM5MS9DTj1IdWF3\r\n"
    "ZWkgQ0JHIEVxdWlwbWVudCBTMSBDQSBUZXN0LE9VPUh1YXdlaSBDQkcsTz1IdWF3\r\n"
    "ZWksQz1DTj9jQUNlcnRpZmljYXRlO2JpbmFyeTBrBggrBgEFBQcwBaRfMF0xCzAJ\r\n"
    "BgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcx\r\n"
    "KDAmBgNVBAMMH0h1YXdlaSBDQkcgRXF1aXBtZW50IFMxIENBIFRlc3QwVwYIKwYB\r\n"
    "BQUHMAWGS2h0dHA6Ly9wa2kub2xhLWlvdC5jb206MTAwMDQvZWNjZmlsZS9IdWF3\r\n"
    "ZWlDQkdFcXVpcG1lbnRTMUNBVGVzdDEwMDAwMDBmLmNlcjAKBggqhkjOPQQDAwNo\r\n"
    "ADBlAjEA9Sxu6IrgkxWXT2zh3Py11dbPcrPnQ+7j/7z1p33+OGyDBCbTfGKXYiEr\r\n"
    "MPGcdJ4HAjAsmvSpSAYLu1o7FH56DYE/1uZvRyK7yjPL22qReGrwodKzxP2MN8aU\r\n"
    "PLNwo9cJy1w=\r\n"
    "-----END CERTIFICATE-----\r\n"
    "";

/* 预置 GlobalSign Root CA - R3 根证书 */
static const unsigned char g_caPem2[] =
        "-----BEGIN CERTIFICATE-----\r\n"
    "MIIC4DCCAmWgAwIBAgIEEAAADTAKBggqhkjOPQQDAzA1MQswCQYDVQQGEwJDTjEM\r\n"
    "MAoGA1UECgwDT0xBMRgwFgYDVQQDDA9PTEEgRUNDIFJPT1QgQ0EwIBcNMjEwNDA4\r\n"
    "MTE0NDE4WhgPMjA1MTA0MDExMTQ0MThaMDUxCzAJBgNVBAYTAkNOMQwwCgYDVQQK\r\n"
    "DANPTEExGDAWBgNVBAMMD09MQSBFQ0MgUk9PVCBDQTB2MBAGByqGSM49AgEGBSuB\r\n"
    "BAAiA2IABB6gqFoYr/qxANCBOPZ+FMcb96OzLt1ZnWgXopFBPj/BMW/s030cZbTn\r\n"
    "lOnWZtv45EtxDovoHM40Gb75RibrTCwZjjpjI2OHKt31yB2DgCP7PZoP1gpXuB+A\r\n"
    "IBnQX7cB9KOCAUIwggE+MA4GA1UdDwEB/wQEAwIBBjCB+wYIKwYBBQUHAQsEge4w\r\n"
    "geswWQYIKwYBBQUHMAWGTWxkYXA6Ly9wa2kub2xhLWlvdC5jb206MzkxL0NOPU9M\r\n"
    "QSBFQ0MgUk9PVCBDQSxPPU9MQSxDPUNOP2NBQ2VydGlmaWNhdGU7YmluYXJ5MEMG\r\n"
    "CCsGAQUFBzAFpDcwNTELMAkGA1UEBhMCQ04xDDAKBgNVBAoMA09MQTEYMBYGA1UE\r\n"
    "AwwPT0xBIEVDQyBST09UIENBMEkGCCsGAQUFBzAFhj1odHRwOi8vcGtpLm9sYS1p\r\n"
    "b3QuY29tOjEwMDA0L2VjY2ZpbGUvT0xBRUNDUk9PVENBMTAwMDAwMGQuY2VyMA8G\r\n"
    "A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMeV6WvW4lUZ9u38cANgvFOlV7XgMAoG\r\n"
    "CCqGSM49BAMDA2kAMGYCMQCi26ZNn3rvFgKQcdZ2rdPxgSqByUGYLtL9c0bqCLqu\r\n"
    "8372CuUZak0VT2IHeFViL4YCMQCN1q7DALPgy8pdixd3oxcXLvWyniDO3BO15EDz\r\n"
    "DMPqtj+H3XJx30KxKIFeKgMYk9k=\r\n"
    "-----END CERTIFICATE-----\r\n"
    "";

static const unsigned char *g_caCert[CERT_NUMBER] = { g_caPem1, g_caPem2 };
static CertValidDate g_certDate[MAX_CERT_DEPTH];
static unsigned int g_unCheckCertNum = 0;

/* ciphersuites数组以0为结尾，需预留 */
static int g_supportedCiphersuites[MAX_CIPHERSUITES_NUM + 1];
static bool g_supportedSuitesInit = true;

static mbedtls_time_t GetCurrentTime(mbedtls_time_t *timeNow)
{
    time_t rawSeconds;

    /* 此参数可能为空 */
    (void)timeNow;
    unsigned long long timeMs = 0;
#ifdef OLA_DEBUG
    int ret = OLA_ERROR;
#else
    int ret = OlaGetUtcTimeMs(&timeMs);
#endif
    if (ret == OLA_OK) {
        rawSeconds = (time_t)(timeMs / MS_PER_SECOND);
    } else {
        rawSeconds = 0;
        OlaLogError("get local time failed, set rawSeconds=0");
    }
    return (mbedtls_time_t)rawSeconds;
}

/* 获取固定长度随机数，注册给mbedtls的回调函数 */
static int HardwarePoll(void *data, unsigned char *output, size_t len, size_t *outLen)
{
    (void)data;
    if ((output == NULL) || (len == 0) || (outLen == NULL)) {
        OlaLogWarning("invalid params.");
        return -1;
    }

    int ret = OlaRand(output, len);
    if (ret != OLA_OK) {
        OlaLogWarning("get random error");
        return -1;
    }
    *outLen = len;
    return 0;
}

static void InitTlsResource(OlaTlsResource *resource)
{
    (void)memset_s(g_certDate, sizeof(g_certDate), 0, sizeof(g_certDate));
    /* 初始化网络结构体 */
    mbedtls_net_init(&resource->ctx);
    /* 初始化ssl结构体 */
    mbedtls_ssl_init(&resource->ssl);
    /* 初始化ssl配置结构体 */
    mbedtls_ssl_config_init(&resource->conf);
    /* 初始化随机结构体 */
    mbedtls_ctr_drbg_init(&resource->ctrDrbg);
    /* 初始化X.509结构体 */
    mbedtls_x509_crt_init(&resource->srvCert);
    /* 初始化熵结构体 */
    mbedtls_entropy_init(&resource->entropy);
}

static int SaveCertTime(const struct mbedtls_x509_crt *crt, unsigned int *flags)
{
    if ((((*flags & MBEDTLS_X509_BADCERT_EXPIRED) != 0) ||
        ((*flags & MBEDTLS_X509_BADCERT_FUTURE) != 0)) && (g_unCheckCertNum < MAX_CERT_DEPTH)) {
        if ((memcpy_s(&g_certDate[g_unCheckCertNum].start, sizeof(mbedtls_x509_time),
                      &crt->valid_from, sizeof(mbedtls_x509_time)) != OLA_OK) ||
            (memcpy_s(&g_certDate[g_unCheckCertNum].end, sizeof(mbedtls_x509_time),
                      &crt->valid_to, sizeof(mbedtls_x509_time)) != OLA_OK)) {
            OlaLogError("memcpy_s error");
            return OLA_SECUREC_ERR_MEMCOPY;
        }
        g_unCheckCertNum++;
        /* flags去掉证书有效期校验失败的标记 */
        *flags &= ~(MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCERT_FUTURE);
    }
    return OLA_OK;
}

static int VerifyCert(struct mbedtls_x509_crt *crt, unsigned int *flags)
{
    int ret;
    for (unsigned int i = 1; i < CERT_NUMBER; i++) {
        mbedtls_x509_crt caCert;
        (void)memset_s(&caCert, sizeof(mbedtls_x509_crt), 0, sizeof(mbedtls_x509_crt));
        mbedtls_x509_crt_init(&caCert);
        if (mbedtls_x509_crt_parse(&caCert, g_caCert[i], strlen((const char *)g_caCert[i]) + 1) != 0) {
            mbedtls_x509_crt_free(&caCert);
            OlaLogError("x509 crt parse error");
            return OLA_MBEDTLS_ERR_X509_CRT_PARSE;
        }
        ret = mbedtls_x509_crt_verify(crt, &caCert, NULL, NULL, (uint32_t *)flags, NULL, NULL);
        if ((ret != 0) && (ret != MBEDTLS_ERR_X509_CERT_VERIFY_FAILED)) {
            mbedtls_x509_crt_free(&caCert);
            continue;
        }
        /* 此时先不检查证书时间，待同步到时间后再校验 */
        if ((((*flags & MBEDTLS_X509_BADCERT_EXPIRED) != 0) ||
            ((*flags & MBEDTLS_X509_BADCERT_FUTURE) != 0)) && (g_unCheckCertNum < MAX_CERT_DEPTH)) {
            if ((memcpy_s(&g_certDate[g_unCheckCertNum].start, sizeof(mbedtls_x509_time),
                          &crt->valid_from, sizeof(mbedtls_x509_time)) != EOK) ||
                (memcpy_s(&g_certDate[g_unCheckCertNum].end, sizeof(mbedtls_x509_time),
                          &crt->valid_to, sizeof(mbedtls_x509_time)) != EOK)) {
                OlaLogError("memcpy_s error");
                return OLA_SECUREC_ERR_MEMCOPY;
            }
            g_unCheckCertNum++;
            /* flags去掉证书有效期校验失败的标记 */
            *flags &= ~(MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCERT_FUTURE);
            mbedtls_x509_crt_free(&caCert);
            break;
        } else if (*flags == 0) {
            mbedtls_x509_crt_free(&caCert);
            break;
        } else {
            mbedtls_x509_crt_free(&caCert);
            continue;
        }
    }
    return OLA_OK;
}

/* 注册给mbedtls的回调函数 */
static int VerifyCertProc(const void *data, struct mbedtls_x509_crt *crt, int depth, unsigned int *flags)
{
    int ret;
    /* mbedtls的回调函数参数，因此这里校验下更健壮 */
    do {
        if ((crt == NULL) || (flags == NULL)) {
            OlaLogError("invalid params.");
            return -1;
        }

        ret = SaveCertTime(crt, flags);
        if (ret != OLA_OK) {
            return -1;
        }
        /* flag等于0表示证书校验通过，depth等于0表示验证设备证书 */
        if ((*flags == 0)|| (depth == 0)) {
            break;
        }

        ret = VerifyCert(crt, flags);
        if (ret != OLA_OK) {
            OlaLogWarning("verify cert error %d", ret);
            return -1;
        }
    } while (0);

    if (data == NULL) {
        return 0;
    }

    const VerifyCertFunc checkFunc = (const VerifyCertFunc)data;
    ret = checkFunc(crt, depth, flags);
    if (ret != OLA_OK) {
        OlaLogWarning("custom verify cert error %d", ret);
        return -1;
    }
    return 0;
}

static bool IsValidMbedtlsCiphersuites(const mbedtls_ssl_ciphersuite_t *suite)
{
    if (suite == NULL) {
        return false;
    }
    unsigned int i;
    for (i = 0; i < MAX_SUPPORT_CIPHERSUITE_NUM; ++i) {
        if (suite->id == SUPPORT_CIPHERSUITE[i]) {
            return true;
        }
    }
    return false;
}

static void ConfigTlsCipherSuites(mbedtls_ssl_config *config)
{
    if (config == NULL) {
        OlaLogError("invalid params.");
        return ;
    }

    if (g_supportedSuitesInit == true) {
        const int *curSuite = mbedtls_ssl_list_ciphersuites();
        int *supportSuite = g_supportedCiphersuites;
        for (; (curSuite != NULL) && (*curSuite != 0) &&
            (supportSuite < g_supportedCiphersuites + MAX_CIPHERSUITES_NUM); ++curSuite) {
            const mbedtls_ssl_ciphersuite_t *info = mbedtls_ssl_ciphersuite_from_id(*curSuite);
            if (!IsValidMbedtlsCiphersuites(info)) {
#ifdef OLA_DEBUG
                continue;
#endif
            }
            *supportSuite = *curSuite;
            ++supportSuite;
        }
        *supportSuite = 0;
        g_supportedSuitesInit = false;
    }
    /* 配置加密套件 */
    mbedtls_ssl_conf_ciphersuites(config, g_supportedCiphersuites);
}

static int TlsSocketConfig(int fd)
{
    unsigned int timeout = TLS_TCP_READ_TIMEOUT;
    int ret = OlaSetSocketOpt(fd, OLA_SOCKET_OPTION_READ_TIMEOUT, &timeout);
    if (ret != 0) {
        OlaLogError("set socket read timeout error");
        return OLA_SOCKET_ERR_SET_RECV_TIMEOUT;
    }

    timeout = TLS_TCP_SEND_TIMEOUT;
    ret = OlaSetSocketOpt(fd, OLA_SOCKET_OPTION_SEND_TIMEOUT, &timeout);
    if (ret != 0) {
        OlaLogError("set socket send timeout error");
        return OLA_SOCKET_ERR_SET_SEND_TIMEOUT;
    }
    return OLA_OK;
}

static int TlsMbedtlsRngConfig(OlaTlsResource *resource, const char *custom)
{
    /* 添加熵源接口，设置熵源属性 */
    int ret = mbedtls_entropy_add_source(&resource->entropy, HardwarePoll, NULL,
        MBEDTLS_ENTROPY_MIN_HARDCLOCK, MBEDTLS_ENTROPY_SOURCE_STRONG);
    if (ret != 0) {
        OlaLogError("add entropy source error [%d]", ret);
        return OLA_MBEDTLS_ERR_ENTROPY_ADD_SOURCE;
    }

    OlaLogDebug("Seeding the random number generator...");
    unsigned int customLen = (custom == NULL) ? 0 : strlen(custom);
    /* 根据个性化字符串更新种子 */
    ret = mbedtls_ctr_drbg_seed(&resource->ctrDrbg, mbedtls_entropy_func, &resource->entropy,
        (const unsigned char*)custom, customLen);
    if (ret != 0) {
        OlaLogError("ctr drbg seed error [%d]", ret);
        return OLA_MBEDTLS_ERR_CTR_DRBG_SEED;
    }
    /* 设置随机数生成器回调接口 */
    mbedtls_ssl_conf_rng(&resource->conf, mbedtls_ctr_drbg_random, &resource->ctrDrbg);

    return OLA_OK;
}

static int TlsMbedtlsCommonConfig(OlaTlsResource *resource)
{
    /* 加载ssl默认配置选项，可以指定端类型、传输协议等参数 */
    int ret = mbedtls_ssl_config_defaults(&resource->conf, MBEDTLS_SSL_IS_CLIENT,
        MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
    if (ret != 0) {
        OlaLogError("ssl config error [%d]", ret);
        return OLA_MBEDTLS_ERR_SSL_CONFIG_DEFAULTS;
    }
    mbedtls_ssl_conf_min_version(&resource->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
    mbedtls_ssl_conf_max_version(&resource->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
    ret = mbedtls_ssl_conf_max_frag_len(&resource->conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096);
    if (ret != 0) {
        OlaLogError("ssl conf max frag return [%d]", ret);
        return OLA_MBEDTLS_ERR_SSL_CONF_MAX_FRAG_LEN;
    }

    return OLA_OK;
}

static int TlsMbedtlsCertConfig(OlaTlsResource *resource,  VerifyCertFunc func)
{
    g_unCheckCertNum = 0;
    /* 配置认证方式，MBEDTLS_SSL_VERIFY_REQUIRED代表对证书进行校验，而且要求证书必须通过校验，否则将终止握手过程 */
    mbedtls_ssl_conf_authmode(&resource->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
    /* X.509证书解析 */
    int ret = mbedtls_x509_crt_parse(&resource->srvCert, g_caCert[0], strlen((const char *)g_caCert[0]) + 1);
    if (ret < 0) {
        OlaLogError("x509 crt parse return [%d]", ret);
        return OLA_MBEDTLS_ERR_X509_CRT_PARSE;
    }
    /* 配置证书链 */
    mbedtls_ssl_conf_ca_chain(&resource->conf, &resource->srvCert, NULL);
    mbedtls_ssl_conf_verify(&resource->conf,
        (int (*)(void *, mbedtls_x509_crt *, int, uint32_t *))VerifyCertProc, func);
    /* 返回值一直为0，判断无意义 */
    (void)mbedtls_platform_set_time(GetCurrentTime);

    ConfigTlsCipherSuites(&resource->conf);
    return  OLA_OK;
}

static int TlsMbedtlsFinshConfig(int fd, OlaTlsResource *resource, const char *url)
{
    resource->ctx.fd = fd;
    /* 通过配置选项完成ssl的设置 */
    int ret = mbedtls_ssl_setup(&resource->ssl, &resource->conf);
    if (ret != 0) {
        OlaLogError("failed, mbedtls_ssl_setup return [%d]", ret);
        return OLA_MBEDTLS_ERR_SSL_SETUP;
    }
    /* 配置ssl hostname */
    ret = mbedtls_ssl_set_hostname(&resource->ssl, url);
    if (ret != 0) {
        OlaLogError("failed, mbedtls_ssl_set_hostname return [%d]", ret);
        return OLA_MBEDTLS_ERR_SSL_SET_HOSTNAME;
    }
    /* 配置网络数据发送和接收接口 */
    mbedtls_ssl_set_bio(&resource->ssl, &resource->ctx, mbedtls_net_send, mbedtls_net_recv, NULL);
    return OLA_OK;
}

static int TlsMbedtlsConfig(int fd, OlaTlsResource *resource, const char *custom,
    const char *url, VerifyCertFunc func)
{
    InitTlsResource(resource);
    int ret = TlsMbedtlsRngConfig(resource, custom);
    if (ret != OLA_OK) {
        OlaLogWarning("set tls rng error");
        return ret;
    }

    ret = TlsMbedtlsCommonConfig(resource);
    if (ret != OLA_OK) {
        OlaLogWarning("set tls common error");
        return ret;
    }

    ret = TlsMbedtlsCertConfig(resource, func);
    if (ret != OLA_OK) {
        OlaLogWarning("set tls cert error");
        return ret;
    }

    ret = TlsMbedtlsFinshConfig(fd, resource, url);
    if (ret != OLA_OK) {
        OlaLogWarning("finsh tls conf error");
        return ret;
    }
    return OLA_OK;
}

static int TlsHandshake(OlaTlsResource *resource)
{
    int ret;
    unsigned long long startTime = 0;
    if (OlaGetTime(&startTime) != OLA_OK) {
        OlaLogWarning("get time failed");
        return OLA_ERROR;
    }
    bool isTimeout = false;
    while (!isTimeout) {
        ret = mbedtls_ssl_handshake(&resource->ssl);
        if ((ret < 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
            OlaLogError("ssl handshake error [%d]", ret);
            return OLA_MBEDTLS_ERR_SSL_HANDSHAKE;
        } else if (ret == 0) {
            return OLA_OK;
        }
        ret = OlaIsOvertime(&isTimeout, startTime, TLS_HANDSHAKE_TIMEOUT);
        if (ret != OLA_OK) {
            OlaLogError("overtime check error");
            return ret;
        }
    }

    return OLA_MBEDTLS_ERR_SSL_HANDSHAKE_TIMEOUT;
}

int OlaTlsClientConfig(int fd, OlaTlsResource *resource, const char *custom,
    const char *url, VerifyCertFunc func)
{
    /* custom和func有可能为空 */
    if ((resource == NULL) || (url == NULL) || (fd < 0)) {
        OlaLogWarning("invalid param");
        return OLA_COM_ERR_INVALID_ARGUMENT;
    }

    int ret = TlsSocketConfig(fd);
    if (ret != OLA_OK) {
        OlaLogWarning("socket config error");
        return ret;
    }

    do {
        ret = TlsMbedtlsConfig(fd, resource, custom, url, func);
        if (ret != OLA_OK) {
            OlaLogWarning("tls config error");
            break;
        }

        ret = TlsHandshake(resource);
        if (ret != OLA_OK) {
            OlaLogWarning("tls handshake error");
            break;
        }
    } while (false);
    if (ret != OLA_OK) {
        OlaReleaseTlsResource(resource);
        return ret;
    }
    return OLA_OK;
}

void OlaReleaseTlsResource(OlaTlsResource *resource)
{
    if (resource == NULL) {
        return;
    }

    (void)memset_s(g_certDate, sizeof(g_certDate), 0, sizeof(g_certDate));
    g_unCheckCertNum = 0;

    mbedtls_ssl_free(&resource->ssl);
    mbedtls_ssl_config_free(&resource->conf);
    mbedtls_ctr_drbg_free(&resource->ctrDrbg);
    mbedtls_x509_crt_free(&resource->srvCert);
    mbedtls_entropy_free(&resource->entropy);
    (void)memset_s(resource, sizeof(OlaTlsResource), 0, sizeof(OlaTlsResource));
    resource->ctx.fd = OLA_INVALID_FD;
}

int OlaValidateCertDate(void)
{
    int ret = OLA_OK;
    unsigned int i;
    bool flag = true;
    do {
        for (i = 0; (i < g_unCheckCertNum) && (i < MAX_CERT_DEPTH); i++) {
            if (mbedtls_x509_time_is_future(&g_certDate[i].start) != 0) {
                ret = OLA_ERROR;
                flag=false;
                break;
            }

            if (mbedtls_x509_time_is_past(&g_certDate[i].end) != 0) {
                ret = OLA_ERROR;
                flag=false;
                break;
            }
        }
    } while (flag);

    (void)memset_s(g_certDate, sizeof(g_certDate), 0, sizeof(g_certDate));
    g_unCheckCertNum = 0;
    return ret;
}
